账户金额 = 0
def ATM机(金额, 存钱=True):
    global 账户金额  # 全局变量

    if 存钱:  # 传参默认是真, 如果传参是 假,执行下面的
        账户金额 += 金额
        print(f'存款{金额} 账户余额{账户金额}')
    else:
        账户金额 -= 金额
        print(f'取款{金额} 账户余额{账户金额}')

# -----------------------------------------------------

ATM机(200)
ATM机(40, False)
print()
"""
看上面的示例 这里有个问题就是全局变量,有篡改的风险

这里我们引入一个概念(功能)  闭包
在函数嵌套的前提下,内部函数使用了外部函数的变量,并且外部函数返回了内部函数,我们把这个使用外部函数变量的内部函数称之为 闭包
"""


# -----------------------------------------------------
def 文本(两边):  # 外部函数

    def 一行文本(中间):  # 内部函数
        print(f"<{两边}>{中间}<{两边}>")  # 内部函数使用外部变量  这个内部函数我们就叫 闭包

    return 一行文本  # 内部函数作为返回值 注意这里不带括号


fn = 文本("大家好")  # 注意这里 fn 变量是函数,因为返回值是 内部函数
fn("孙新罡")  # 我们看 fn 个函数,在赋值,看看输出结果
fn("张艳艳")  # 我们看外部函数的变量,一直不变的
print()
"""
要理解 内部函数要用外部函数的变量,同时外部函数的返回值是 内部函数
在赋值操作时,可以把变量变成函数了  然后在操作内部函数

这样操作的目的 使得我们使用函数 相当于有一个全局变量,但是又不能修改它. 不想最上面的 全局变量有篡改的风险
因为这里的外部函数的变量是一个临时变量,而内部函数使用 外部函数的变量,相当于得到了一个全局变量
"""
"""
那如果我们想修改,外部函数的变量怎么办
需要使用nonlocal关键字修饰外部函数的变量,才能在内部函数中修改它
"""


外数字 =1585  # 外界的变量,对函数没有影响了. 这样不存在篡改的风险了
def 外部(外数字):
    def 内部(内数字):
        nonlocal 外数字  # 外部变量本来只能,临时调用的. 加上这个关键字使得我们可以对外部变量 永久性修改了
        外数字 += 内数字
        print(f"内部函数:{外数字}")

    return 内部  # 返回值就是 闭包函数


计算1 = 外部(10)  # 先赋值外部变量10
计算1(10)  # 看看连续的2次输出,结果.  证明外部变量不是临时调用而是保持了赋值的持续性
计算1(2)
print()
# -----------------------------------------------------

# 下面用闭包的方法重新写最上面的ATM机程序


def 外部ATM(账户金额=0):  # 默认金额0

    def ATM机(金额, 存钱=True):  # 闭包函数
        nonlocal 账户金额  # 外部变量, 但相当于内部函数的全局变量

        if 存钱:  # 传参默认是真, 如果传参是 假,执行下面的
            账户金额 += 金额
            print(f'存款{金额} 账户余额{账户金额}')
        else:
            账户金额 -= 金额
            print(f'取款{金额} 账户余额{账户金额}')

    return ATM机  # 小这样 返回值的层级在哪里,要在外部函数的层级哦


银行1 = 外部ATM()
银行1(1123)
银行1(123, 存钱=False)  # 存钱又取钱的操作,看看输出结果
print()

银行2 = 外部ATM()
银行2(474)
银行2(633, False)

"""
闭包的优缺点
优点,使用闭包可以让我们得到:
无需定义全局变量,即可实现通过函数,持续地访问 修改某个值
闭包使用的变量作用域,在函数内(内部函数),难以被错误的调用修改  避免了篡改

缺点:
由于内部函数持续引用外部函数的值,所以会造成一部分内存空间不被释放,一直占用内存
"""

"""
总结 什么是 闭包
定义双层嵌套函数, 内层函数可以访问外层函数的变量. 将内层函数作为外层函数的返回值. 此内存函数就是 闭包函数

nonlocal 关键字的作用
在闭包函数(内部函数) 中想要修改外部函数的变量值
需要用 nonlocal 声明这个外部变量, 这样可以持续修改外部变量并保存下来


"""